perm filename A46.TEX[106,RWF] blob
sn#848174 filedate 1987-11-04 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00002 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 %to a09.tex
C00021 ENDMK
C⊗;
%to a09.tex
\magnification\magstephalf
\input macro.tex
\def\today{\ifcase\month\or
January\or February\or March\or April\or May\or June\or
July\or August\or September\or October\or November\or December\fi
\space\number\day, \number\year}
\baselineskip 14pt
\rm
\line{\sevenrm a46.tex[106,phy] \today\hfill}
\bigskip
\line{\bf Overflow and Underflow\hfil}
\smallskip
\line{\it Yo Feet's Too Big\hfil}
The Pascal Standard tacitly acknowledges that present-day computers are
designed to work with numbers of limited size and precision.
Integers are limited in size to having absolute values no greater than the
symbolic constant {\tt MAXINT}, which is implementation-defined; that is,
it has different values on different computers. A~computation which at any
stage attempts to produce a larger integer value than {\tt MAXINT} is not
defined. In practice, that means it may give an undetected wrong answer,
or that it may stop with or without explanation. Integer computations with all
intermediate and final results in the range {\tt $\pm$~MAXINT}, however,
are performed exactly.
Computation on real numbers is left almost entirely undefined by Standard
Pascal. In practice, real numbers must lie in certain ranges, and are
computed with high enough precision for most scientific and engineering
computation. The details of precision are discussed later; typical range
restrictions are presented here.
Usually, numbers must fall in three ranges, as shown schematically below.
$$\vcenter{\offinterlineskip
\halign{\hfil#\hfil\qquad&\hfil#\xskip&\hfil#\hfil\xskip\hfil\qquad&\hfil#\hfil\cr
{\tt MAXNEGREAL}&{\tt MINNEGREAL}&&{\tt MINREAL}&{\tt MAXREAL}\cr
\noalign{\smallskip}
$\downarrow$&$\searrow$&&$\swarrow$&$\downarrow$\cr
$\bullet$&$\bullet$&$\bullet$&$\bullet$&$\bullet$\cr
\noalign{\smallskip}
&&0\cr}}$$
\noindent For discussion, we call the ends of the negative range
{\tt MAXNEGREAL} and {\tt MINNEGREAL}, and the ends of the positive range
{\tt MINREAL} and {\tt MAXREAL}. These names are not part of Standard Pascal.
The absolute values of {\tt MAXREAL} and {\tt MAXNEGREAL} are quite large,
perhaps around $10↑{38}$ or~$10↑{76}$; often they are equal. Those of
{\tt MINREAL} and {\tt MINNEGREAL} are quite small, but not zero, perhaps
around $10↑{-39}$ or $10↑{-77}$; again, equality is common. If a number
is greater than {\tt MAXREAL}, or less than {\tt MAXNEGREAL}, it is out
of the range Pascal can represent; an attempt to compute such a~number
is called {\it overflow\/}. An overflow may give rise to an undetected
wrong answer, or the program may stop with or without explanation. Similarly,
a~non-zero number between {\tt MINREAL} and {\tt MINNEGREAL} is out of
range; an attempt to compute such a number is called {\it underflow\/},
and may give rise to much the same unpleasantness as overflow.
Suppose {\tt MAXREAL} were $9.999\times 10↑9$ and {\tt MINREAL} were
$1.000\times 10↑{-9}$. Examples of overflow would be
$5000000000.0+6.000000000.0$, $3.00000.0\times 40000.0$, and
$1234567890/0.0002$; examples of underflow would be
$1/50000-1/49999$, $(1/50000)\ast(1/49999)$, and $(1/50000)/49999$.
Some common values of {\tt MAXINT}, {\tt MAXREAL}, and {\tt MINREAL} are
shown below:
$$\vcenter{\halign{#\hfil\qquad&\hfil#\hfil\qquad&\hfil#\hfil\qquad%
&\hfil#\hfil\qquad&\hfil#\hfil\cr
Computer&Word length&{\tt MAXINT}&{\tt MAXREAL}&{\tt MINREAL}\cr
\noalign{\smallskip}
DEC-20&36&34,359,738,367&$1.7\ast 10↑{38}$&$1.5\ast 10↑{-39}$\cr
VAX&16&\phantom{3}2,147,483,647&$1.7\ast 10↑{38}$&$2.9\ast 10↑{-39}$\cr
IBM 360, 370, 30xx, 43xx&32&\phantom{3}2,147,483,647&$7.2\ast
10↑{75}$&$5.4\ast 10↑{-79}$\cr
IBM PC&16&\phantom{34,359,7}32,767\cr}}$$
\noindent
While overflow and underflow are not common, the wise programmer will take
precautions against them, remembering that a program that always works
on one computer may overflow on another.
As an example of how an underflow might arise in an otherwise reasonable
program, consider computing an approximate value of~$e↑x$ by the
polynomial $1+x+x↑2/2+x↑3/6+\cdots +x↑{10}/10!$; on some computers, the
last term will underflow when $|x|$ is around 0.0001.
\bigskip
{\baselineskip0pt
\line{\bf\phantom{Wh}Good\hfill}
\line{\bf What $\,$ Are the Standard Functions of Pascal?\hfill}
\line{\bf\phantom{What}$\,↑{∧}$\hfill}}
Every standard operator and function of a programming language, ideally, is
included for the same reason that I~include a tool in my toolbox:
it's so useful that it's worth the effort of carrying it around. I don't agree
with all the choices the designers of Pascal made, but I'll try to show why
they felt a certain set of functions was useful.
\bigskip\noindent
{\bf Standard Functions.}
{\tt SQR$(x)$} is the square of~$x$.
Pascal does not have a built in operation to raise
a number to an arbitrary power, because the best choice of algorithm depends on
so many considerations, only the programmer should decide it. {\tt SQR}$(x)$
is the most common case, and many others like
$x↑8= {\tt SQR}\bigl({\tt SQR}({\tt SQR}(x))\bigr)$,
can be built up from it. The
argument may be {\tt REAL} or {\tt INTEGER};
the result has the same type. The only pitfall
is overflow if $x$~is an integer larger than
$\sqrt{\tt MAXINT}$, or a real larger than $\sqrt{\tt MAXREAL}$.
{\tt SQRT}$(x)$ is the positive square root of~$x$, where $x$~may
be {\tt REAL} or {\tt INTEGER}; the
result is {\tt REAL}.
The pitfall is that the function is lethally undefined if
$x<0$. In some situations, exact calculation of~$x$ would make~$x$ positive,
but rounding errors make it negative.
This pitfall may occur in \naive\ statistical
calculations of standard deviations, especially
where the mean is much larger than the standard deviation.
{\tt ABS}$x$ is the absolute value of~$x$,
where $x$~may be {\tt REAL} or {\tt INTEGER}; the result is of
the same type.
It is used frequently in programming to test whether the difference
between two numbers is small, as in
{\obeylines\obeyspaces\let =\ \tt
IF ABS($x$-$y$)<0.000001 THEN ...
}
\smallskip\noindent
The only pitfall: some systems have a negative integer equal to
{\tt -(MAXINT+1)}; if $x$~has that value, {\tt ABS}$(x)$
overflows.
{\tt SIN}$(x)$, {\tt COS}$(x)$
are the standard trigonometric functions sine and cosine, where~$x$
({\tt REAL} or {\tt INTEGER})
is measured in radians; the result is {\tt REAL}. If $x$~is
measured in degrees, use
$\sin(\pi x/180)$, where $\pi =3.141592654$. Other direct
trigonometric functions such as $\tan(x)=\sin(x)/\cos(x)$
are usually computed from the sine and cosine.
The major pitfall of {\tt SIN} and {\tt COS} is that if
$x$~is much larger than~1, {\sl relatively\/} small rounding errors
in~$x$ give rise to errors in {\tt SIN}$(x)$ and {\tt COS}$(x)$
that are {\sl relatively\/} large. For example, if $x=10↑6$, a~relatively
small error of $0.01=10↑{-8}x$ in~$x$ gives rise to
a relatively large error, possibly near 0.01, in {\tt SIN}$(x)$, which
is no greater than one.
{\tt ARCTAN}$(x)$is the angle between $-\pi/2$ and $\pi/2$ whose tangent
is~$x$; $x$~is {\tt REAL} or
{\tt INTEGER}, and the {\tt REAL}
result is measured in radians. For a result in degrees,
use $180\arctan(x)/\pi$. The only serious pitfall arises when computing
{\tt ARCTAN}$(x/y)$; if~$y$
becomes zero, division overflow occurs, even though the desired angle
is well defined. To avoid this, use (say)
$\pi/4-${\tt ARCTAN}$(x/y)$ when $|x/y|>1$.
{\tt EXP}$(x)$ is the exponential function $e↑x$, where $e$ is 2.718281828;
$x$~is {\tt REAL} or
{\tt INTEGER}, and the result is {\tt REAL}.
Overflow occurs unless $x$~is in the range
${\tt LN(MINREAL)} ≤x≤ {\tt LN(MAXREAL)}$, typically limiting~$x$ to
about~$\pm 88$.
Another minor pitfall is that if $x$~is in the outer
portion of its range, {\sl relatively\/} small rounding errors in~$x$ result in
{\sl relatively\/} larger errors in {\tt EXP}$(x)$, by a factor of nearly~200.
{\tt LN}$(x)$ is the natural (base~$e$) logarithm of~$x$; $x$~is
{\tt REAL} or {\tt INTEGER}, with a
{\tt REAL} result. For base 10 logarithms, use $\ln(x)/\ln(10)$
or the non-standard
function {\tt LOG}$(x)$. A~pitfall is the lethal error $x≤0$.
Less obvious is that if
$x$~is close to~1, a~{\sl relatively\/} small error in~$x$
can result in {\sl relatively\/}
enormous errors in {\tt LN}$(x)$;
for example, changing $x$ from 1.0001 to 1.0002 doubles {\tt LN}$(x)$.
{\tt TRUNC}$(x)$ is the integer part of a real number~$x$.
{\tt TRUNC(2.0)=TRUNC(2.99)=2}; symmetrically,
{\tt TRUNC(-2.0)=TRUNC(-2.99)=-2}.
{\tt TRUNC} is useful in going from ``how much'' to
``how many'', as in determining how many standard sized shelves can be cut
from a board, {\sl but\/} it is seldom right to use {\tt TRUNC}
if $x$~is negative. If $x$~is
positive, {\tt TRUNC}$(x)$ is the largest integer that doesn't
exceed~$x$, but if $x$~is
negative {\tt TRUNC}$(x)$
is larger than~$x$, except when $x$~has an exact integer value.
To classify incomes into \$1000 ranges for tabulation, one might think of using
{\tt TRUNC(INCOME/1000)}, but that formula classifies the much larger
range from $-\$999$ to \$999 as zero.
The non-standard function
${\tt FLOOR}(x)\;\;\bigl($or {\tt ENTIER}$(x)\bigr)$,
the largest integer not
exceeding~$x$, it is probably more useful. Another pitfall is overflow
if $|x|>{\tt MAXINT}$.
To find how many times {\tt B} goes into {\tt A},
both being positive real numbers, use {\tt TRUNC(A/B)}.
{\tt ROUND}$(x)$ is the integer closest to~$x$. If the
fractional part of~$x$ is~1/2, it is
rounded to a larger absolute value. That is,
{\tt ROUND(2.5)=ROUND(3.499)=3};
{\tt ROUND(-2.5)=ROUND(-3.499)=-3}.
The major pitfall of {\tt ROUND} is overflow if
$|x|>{\tt MAXINT}$.
{\tt ORD}$(x)$, where $x$~belongs to any ordinal type ({\tt CHAR}
and enumerated types
especially), is the ({\tt INTEGER}) ordinal number by which~$x$ is enumerated. The
major pitfall is that {\tt ORD} is implementation dependent when $x$~is a
character.
If $x$~is a digit character, however,
${\tt ORD}(x)-{\tt ORD}('0')$ is its numerical value.
Another pitfall is that except for {\tt INTEGER}, the ordinal numbers
of all ordinal types start with zero.
\bigskip
\parindent0pt
\copyright 1984 Robert W. Floyd
First draft March 28, 1984
\bye